#include"TcpServer.hpp"
#include"echo.hpp"
#include<string.h>
#include<time.h>

void HandleClose(Channel* channel)
{
    // std::cout << "close: " << channel->Fd() << std::endl;
    DBG_LOG("close fd:%d " , channel->Fd());
    //调用Channel当中的remove,借助Poller中的RemoveEvent来将事件从epoll模型当中移除
    channel->Remove();
    delete channel;//释放Channel对象,因为Channel对象使用new出来的
}

void HandleRead(Channel* channel)
{
    //读取数据
    int fd = channel->Fd();
    char buffer[1024] = {0};
    ssize_t ret = recv(fd , buffer,1023,0);
    if(ret <= 0)
    {
        //读取数据失败，关闭连接
        HandleClose(channel);
    }
    //数据放在buffer 当中，此时可以启动对该fd 的写事件关心
    channel->EnableWrite();
    // std::cout << buffer << std::endl;
    DBG_LOG("read buffer: %s" , buffer);
}

void HandleWrite(Channel* channel)
{
    int fd = channel->Fd();
    const char* data = "hello world";
    DBG_LOG("write data: %s" , data);

    ssize_t ret = send(fd , data , strlen(data) , 0);
    DBG_LOG("write data success: %s" , data);
    //关闭对该fd 写事件的关心
    channel->DisableWrite();
}

void HandleError(Channel* channel)
{
    //直接释放fd 就可以了
    HandleClose(channel);
}

// void HandleEvent(Channel* channel)
// {
//     //debug
//     std::cout << "有一个事件到来" << std::endl;//每一个连接均会执行这个函数
// }

void HandleEvent(EventLoop* loop, Channel* channel , uint64_t timerid)
{
    //既然每一个连接均会执行此函数，那么在此函数中刷新定时任务
    loop->TimerFlush(timerid);
}

// void Accepter(EventLoop* loop , Channel* listen_sock)
// {
//     uint64_t timerid = rand()%1000;

//     //获取新连接，需要将新连接放入epoll模型中关心其读事件
//     int fd = listen_sock->Fd();
//     int newfd = accept(fd , NULL, NULL);
//     if(newfd < 0) return;
//     //为新连接创建一个Channel对象
//     Channel* channel = new Channel(loop, newfd);
//     //为新Channel对象设置回调函数
//     channel->SetReadCallback(std::bind(HandleRead,channel));
//     channel->SetWriteCallback(std::bind(HandleWrite,channel));
//     channel->SetCloseCallback(std::bind(HandleClose , channel));
//     channel->SetErrorCallback(std::bind(HandleError , channel));
//     channel->SetEventCallback(std::bind(HandleEvent ,loop ,listen_sock,timerid));
//     //将当前连接添加进定时任务
//     loop->TimerAdd(timerid , 10, std::bind(HandleClose , channel));//为新连接设置不活跃就销毁机制
//     //启动新连接的读关心
//     channel->EnableRead();
// }

// int main()
// {
//     EventLoop loop;
//     Socket listen_sock;
//     listen_sock.CreateServer(8888);//创建监听套接字
//     //将监听套接字使用Channel 进行管理
//     Channel channel(&loop , listen_sock.fd());
//     //设置监听套接字的回调函数
//     channel.SetReadCallback(std::bind(Accepter,&loop , &channel));
//     //对监听套接字读事件关心
//     channel.EnableRead();
//     while(1)
//     {
//         loop.Start();//检测哪些fd事件就绪了，并按照就绪的事件去执行相应的任务
//     }
//     //关闭套接字
//     listen_sock.Close();
//     return 0;
// }

// int main()
// {
//     Poller poller;//epoll模型
//     Socket listen_socket;//监听套接字
//     //创建监听套接字--服务器端使用
//     listen_socket.CreateServer(8888);
//     //为监听套接字创建一个Channel 对象进行事件管理、处理;需要传递epoll模型与文件描述符
//     Channel channel(&poller , listen_socket.fd());
//     //向Channel当中添加回调函数,对于监听套接字来说，读回调为获取新连接;
//     //回调函数，为无参;借助于bind 来实现
//     channel.SetReadCallback(std::bind(Accepter , &poller , &channel));
//     //启动监听套接字的读事件监控
//     channel.EnableRead();
//     while(1)
//     {
//         std::vector<Channel*> actives;//管理所有连接的数组
//         //获取活跃的连接
//         poller.Poll(&actives);
//         //遍历活跃的连接
//         for(auto &e:actives)
//         {
//             //调用Channel 当中的事件处理
//             e->HandleEvent();
//         }
//     }
//     return 0;
// }

//管理所有连接的哈希表
std::unordered_map<uint64_t,PtrConnection> _conns;
uint64_t conn_id = 0;//连接id从0开始递增
EventLoop base_loop;
// std::vector<LoopThread> threads(2);
// int next_loop = 0;
LoopThreadPool * loop_pool;

//实现回调函数
void ConnectionDestroy(const PtrConnection& conn)
{
    //将连接从管理连接的哈希表中移除
    _conns.erase(conn->Id());
}

void OnConnected(const PtrConnection& conn)
{
    //debug
    DBG_LOG("new connection: %p" , conn.get());
}

void OnMessage(const PtrConnection& conn , Buffer* buf)
{
    //处理数据的接口
    DBG_LOG("数据：%s" , buf->ReadPostion());
    //此处为拿取出buf中的数据并打印
    buf->MoveReadOffset(buf->ReadAbleSize());
    
    std::string str = "hello world!!!!!!";
    conn->Send(str.c_str() , str.size());
    // conn->Shutdown();//短连接
}

void Accepter(EventLoop* loop , Channel* listen_channel)
{
    int fd = listen_channel->Fd();
    //调用accept获取新连接
    int newfd = accept(fd , nullptr, nullptr);//不关心就设置为空
    //判断返回值是否大于0
    if(newfd <0 )
    {
        if(errno==EINTR || errno == EAGAIN) return;

        ERR_LOG("accept newfd error");
        return;
    }

    //连接id自增，为新连接设置Connection （Connection 中包含了Channel）对象，设置对应的回调函数
    conn_id++;
    PtrConnection conn(new Connection(loop, conn_id,newfd));
    conn->SetConnectedCallBack(std::bind(OnConnected, std::placeholders::_1));
    conn->SetMessageCallBack(std::bind(OnMessage , std::placeholders::_1, std::placeholders::_2));
    conn->SetServerCloseCallBack(std::bind(ConnectionDestroy, std::placeholders::_1));
    //启动连接不活跃就销毁功能
    conn->EnableInactiveRelease(10);
    //就绪初始化
    conn->Established();//修改连接状态，启动对新连接的读事件关心 调用回调函数
    //将这个新连接插入进管理连接的哈希表当中
    _conns.insert(std::make_pair(conn_id , conn));
    DBG_LOG("添加新连接: %d---------------" , newfd);
}


void NewConnection(int fd)
{
    conn_id++;
    // next_loop = (next_loop + 1)%2;//因为只有两个线程
    // PtrConnection conn(new Connection(&base_loop , conn_id , fd));//新连接的Connetion对象
        //从LoopThread 当中获取EventLoop指针
    // PtrConnection conn(new Connection(threads[next_loop].GetLoop(), conn_id,fd));
    PtrConnection conn(new Connection(loop_pool->NextLoop(), conn_id,fd));
    //为新连接设置对应的回调函数
    conn->SetConnectedCallBack(std::bind(OnConnected, std::placeholders::_1));
    conn->SetMessageCallBack(std::bind(OnMessage , std::placeholders::_1, std::placeholders::_2));
    conn->SetServerCloseCallBack(std::bind(ConnectionDestroy, std::placeholders::_1));
    //启动连接不活跃就销毁功能
    conn->EnableInactiveRelease(10);
    //就绪初始化
    conn->Established();//修改连接状态，启动对新连接的读事件关心 调用回调函数
    //将这个新连接插入进管理连接的哈希表当中
    _conns.insert(std::make_pair(conn_id , conn));
    DBG_LOG("添加新连接: %d---------------" , fd);
}

// int main()
// {
//     TcpServer server(8888);
//     server.SetThreadCount(2);
//     server.EnableInactiveRelease(7);
//     //设置回调函数
//     server.SetMessageCallback(OnMessage);
//     server.SetCloseCallback(ConnectionDestroy);
//     server.SetConnectedCallback(OnConnected);
//     server.Start();

//     return 0;
// }

// int main()
// {
//     loop_pool = new LoopThreadPool(&base_loop);
//     loop_pool->SetThreadCount(2);
//     loop_pool->Create();//创建对应数量的LoopThread
//     //创建监听套接字
//     Acceptor acceptor(&base_loop , 8888);
//     //设置其回调函数
//     acceptor.SetAcceptCallback(std::bind(NewConnection , std::placeholders::_1));
//     //设置对于监听套接字的关心
//     acceptor.Listen();
//     while(1)
//     {
//         base_loop.Start();//事件就绪会去执行对应的函数
//     }
//     return 0;
// }

// int main()
// {
//     EventLoop loop;
//     //创建监听套接字、设置其回调函数并关心其读事件
//     Socket listen_socket;
//     listen_socket.CreateServer(8888);
//     //创建channel对象
//     Channel channel(&loop, listen_socket.fd());
//     //设置监听套接字的回调函数
//     channel.SetReadCallback(std::bind(Accepter , &loop, &channel));
//     //关心读事件
//     channel.EnableRead();
//     while(1)
//     {
//         loop.Start();//事件就绪会去执行对应的函数
//     }
//     listen_socket.Close();//关闭文件描述符
//     return 0;
// }


int main()
{
    EchoServer eserver(8888);
    eserver.Start();
    return 0;
}